Using NodesUsing Physics Nodes IIOn this pageUsing Physics Nodes II In this tutorial, we will dive into the advanced functionalities of physical nodes, including: Sensor Functionality: Detects objects entering or leaving a specified area without participating in physical collisions. One-Way Platforms: Create platforms that only allow objects to pass through from one direction using the onContactFilter callback. Handling Collision Events: How to listen to and handle object collision events. With the following example code and explanations, you'll learn how to implement these features in Dora SSR. 1. Creating a Physical World First, initialize the physical world and set the basic parameters. LuaTealTypeScriptYueScriptlocal Vec2 <const> = require("Vec2")local PhysicsWorld <const> = require("PhysicsWorld")local gravity <const> = Vec2(0, -10) -- Define gravity direction and magnitudelocal world = PhysicsWorld() -- Create the physical worldworld:setShouldContact(0, 0, true) -- Set collision rules between groupsworld.showDebug = true -- Show debug informationlocal Vec2 <const> = require("Vec2")local PhysicsWorld <const> = require("PhysicsWorld")local gravity <const> = Vec2(0, -10) -- Define gravity direction and magnitudelocal world = PhysicsWorld() -- Create the physical worldworld:setShouldContact(0, 0, true) -- Set collision rules between groupsworld.showDebug = true -- Show debug informationimport { Vec2, PhysicsWorld } from "Dora";const gravity = Vec2(0, -10); // Define gravity direction and magnitudeconst world = PhysicsWorld(); // Create the physical worldworld.setShouldContact(0, 0, true); // Set collision rules between groupsworld.showDebug = true; // Show debug information_ENV = Doraconst gravity = Vec2 0, -10 -- Define gravity direction and magnitudeworld = with PhysicsWorld! -- Create the physical world \setShouldContact 0, 0, true -- Set collision rules between groups .showDebug = true -- Show debug information 2. Creating a Sensor A sensor is a special physical object that doesn't participate in collisions but can detect other objects entering or leaving its area. 2.1 Defining a Sensor LuaTealTypeScriptYueScriptlocal BodyDef <const> = require("BodyDef")-- Create a hollow circular static body by defining a set of vertices-- Used to restrict the activity area in this examplelocal terrainDef = BodyDef()local count <const> = 50local radius <const> = 300local vertices = {}for i = 1, count + 1 do local angle = 2 * math.pi * i / count vertices[i] = Vec2(radius * math.cos(angle), radius * math.sin(angle))end-- Add a closed chain shape static body definitionterrainDef:attachChain(vertices, 0.4, 0)-- Add a circular sensor area with label number 99terrainDef:attachDiskSensor(99, Vec2(80, 80), 100)local BodyDef <const> = require("BodyDef")-- Create a hollow circular static body by defining a set of vertices-- Used to restrict the activity area in this examplelocal terrainDef = BodyDef()local count = 50local radius = 300local vertices = []for i = 1 to count + 1 do local angle = 2 * math.pi * i / count vertices[i] = Vec2(radius * math.cos(angle), radius * math.sin(angle))end-- Add a closed chain shape static body definitionterrainDef:attachChain(vertices, 0.4, 0)-- Add a circular sensor area with label number 99terrainDef:attachDiskSensor(99, Vec2(80, 80), 100)import { BodyDef, Vec2 } from "Dora";const terrainDef = BodyDef();const count = 50;const radius = 300;const vertices: Vec2.Type[] = [];for (let i = 1; i <= count + 1; i++) { const angle = 2 * math.pi * i / count; vertices.push(Vec2(radius * math.cos(angle), radius * math.sin(angle)));}// Add a closed chain shape static body definitionterrainDef.attachChain(vertices, 0.4, 0);// Add a circular sensor area with label number 99terrainDef.attachDiskSensor(99, Vec2(80, 80), 100);_ENV = DoraterrainDef = with BodyDef! count = 50 radius = 300 vertices = [] for i = 1, count + 1 local angle = 2 * math.pi * i / count vertices[i] = Vec2 radius * math.cos angle, radius * math.sin angle \attachChain vertices, 0.4, 0 -- Add a closed chain shape static body definition \attachDiskSensor 99, Vec2 80, 80, 100 -- Add a circular sensor area with label number 99 attachChain: Creates a chain shape made of multiple vertices. attachDiskSensor: Adds a circular sensor at the specified location that doesn't participate in collisions but can detect objects entering the area. 2.2 Listening to Sensor Events LuaTealTypeScriptYueScriptlocal terrain = Body(terrainDef, world)terrain:onBodyEnter(function(other, sensorTag) if sensorTag == 99 then -- Triggered when an object enters the sensor area other.velocity = other.velocity * 0.5 -- Halve the object's speed endend)terrain:addTo(world)local terrain = Body(terrainDef, world)terrain:onBodyEnter(function(other: Body.Type, sensorTag: integer) if sensorTag == 99 then -- Triggered when an object enters the sensor area other.velocity = other.velocity * 0.5 -- Halve the object's speed endend)terrain:addTo(world)import { BodyDef, Vec2 } from "Dora";const terrain = Body(terrainDef, world);terrain.onBodyEnter((other, sensorTag) => { if (sensorTag == 99) { // Triggered when an object enters the sensor area other.velocity = other.velocity.mul(0.5); // Halve the object's speed }});terrain.addTo(world);terrain = with Body terrainDef, world \onBodyEnter (other, sensorTag) -> if sensorTag == 99 -- Triggered when an object enters the sensor area other.velocity *= 0.5 -- Halve the object's speed \addTo world onBodyEnter: Called when another object enters the sensor area. Callback function parameters: other: The object that entered the sensor. sensorTag: The sensor's label used to distinguish between different sensors. 3. Creating a One-Way Platform Using onContactFilter, we can control the collision behavior and create a platform that only allows objects to pass through from one direction. 3.1 Defining the Platform Body LuaTealTypeScriptYueScriptlocal platformDef = BodyDef()-- Add a rectangular platform definitionplatformDef:attachPolygon( Vec2(0, -80), -- Position 120, 30, -- Width and height 0, -- Angle 1, 0, 1.0 -- Density, friction coefficient, restitution coefficient)local platformDef = BodyDef()-- Add a rectangular platform definitionplatformDef:attachPolygon( Vec2(0, -80), -- Position 120, 30, -- Width and height 0, -- Angle 1, 0, 1.0 -- Density, friction coefficient, restitution coefficient)import { BodyDef, Vec2 } from "Dora";const platformDef = BodyDef();// Add a rectangular platform definitionplatformDef.attachPolygon( Vec2(0, -80), // Position 120, 30, // Width and height 0, // Angle 1, 0, 1.0 // Density, friction coefficient, restitution coefficient);platformDef = with BodyDef! \attachPolygon( Vec2 0, -80 -- Position 120, 30 -- Width and height 0 -- Angle 1, 0, 1.0 -- Add a rectangular platform definition ) 3.2 Setting the Collision Filter LuaTealTypeScriptYueScriptlocal platform = Body(platformDef, world)platform:onContactFilter(function(body) return body.velocityY < 0 -- Only collide when the object is moving downwardend)platform:addTo(world)local platform = Body(platformDef, world)platform:onContactFilter(function(body: Body.Type) return body.velocityY < 0 -- Only collide when the object is moving downwardend)platform:addTo(world)import { Body } from "Dora";const platform = Body(platformDef, world);platform.onContactFilter(body => { return body.velocityY < 0; // Only collide when the object is moving downward});platform.addTo(world);platform = with Body platformDef, world \onContactFilter (body) -> body.velocityY < 0 -- Only collide when the object is moving downward \addTo world onContactFilter: Custom collision detection rules. The callback function returns true to allow the collision and false to ignore it. By checking the object's vertical speed (velocityY), we achieve a one-way collision effect. 4. Handling Collision Events Listening to collision events allows specific logic to be executed, such as playing sound effects or triggering animations. 4.1 Creating a Dynamic Body LuaTealTypeScriptYueScriptlocal BodyDef <const> = require("BodyDef")local diskDef = BodyDef()diskDef.type = "Dynamic"diskDef.linearAcceleration = gravitydiskDef:attachDisk(20, 5, 0.8, 1) -- Create a circular body with a radius of 20local disk = Body(diskDef, world, Vec2(100, 200))disk.angularRate = -1800 -- Set the rotation speeddisk:addTo(world)local BodyDef <const> = require("BodyDef")local diskDef = BodyDef()diskDef.type = "Dynamic"diskDef.linearAcceleration = gravitydiskDef:attachDisk(20, 5, 0.8, 1) -- Create a circular body with a radius of 20local disk = Body(diskDef, world, Vec2(100, 200))disk.angularRate = -1800 -- Set the rotation speeddisk:addTo(world)import { BodyDef, Vec2, BodyMoveType } from "Dora";const diskDef = BodyDef();diskDef.type = BodyMoveType.Dynamic;diskDef.linearAcceleration = gravity;diskDef.attachDisk(20, 5, 0.8, 1); // Create a circular body with a radius of 20const disk = Body(diskDef, world, Vec2(100, 200));disk.angularRate = -1800; // Set the rotation speeddisk.addTo(world);diskDef = with BodyDef! .type = "Dynamic" .linearAcceleration = gravity \attachDisk 20, 5, 0.8, 1 -- Create a circular body with a radius of 20disk = with Body diskDef, world, Vec2 100, 200 .angularRate = -1800 -- Set the rotation speed \addTo world type: Set to dynamic body, affected by the physics engine. attachDisk: Creates a circular-shaped body. 4.2 Listening to Collision Events LuaTealTypeScriptYueScriptlocal Line <const> = require("Line")local App <const> = require("App")-- Create a marker to draw at the collision pointlocal drawNode = Line({ Vec2(-20, 0), Vec2(20, 0), Vec2.zero, Vec2(0, -20), Vec2(0, 20)}, App.themeColor)drawNode:addTo(world)disk:onContactStart(function(other, point) -- Set the marker's position to the collision point drawNode.position = pointend)local Line <const> = require("Line")local App <const> = require("App")-- Create a marker to draw at the collision pointlocal drawNode = Line({ Vec2(-20, 0), Vec2(20, 0), Vec2.zero, Vec2(0, -20), Vec2(0, 20)}, App.themeColor)drawNode:addTo(world)disk:onContactStart(function(other: Body.Type, point: Vec2.Type) -- Set the marker's position to the collision point drawNode.position = pointend)import { Line, App } from "Dora";// Create a marker to draw at the collision pointconst drawNode = Line([ Vec2(-20, 0), Vec2(20, 0), Vec2.zero, Vec2(0, -20), Vec2(0, 20)], App.themeColor);drawNode.addTo(world);disk.onContactStart((other, point) => { // Set the marker's position to the collision point drawNode.position = point;});drawNode = with Line [ Vec2 -20, 0 Vec2 20, 0 Vec2.zero Vec2 0, -20 Vec2 0, 20], App.themeColor \addTo worlddisk\onContactStart (other, point) -> -- Set the marker's position to the collision point drawNode.position = point onContactStart: Called when the body starts colliding with another object. Callback function parameters: other: The other object involved in the collision. point: The world coordinates of the collision point. Use drawNode to display a marker at the collision location, making it easier to visualize. 5. Results By running the above code, you will achieve the following effects: Sensor Functionality: When an object enters the sensor area, its speed is halved, simulating a slowing effect. One-Way Platform: Objects can only fall through the platform from above and cannot pass through from below, achieving a one-way collision. Collision Events: When the circular body collides with other objects, a marker is displayed at the collision point. 6. Summary This tutorial introduced the advanced features of physical nodes, including the use of sensors, how to create one-way platforms, and how to capture and handle collision events. These features can enhance the interactivity of your game and improve the player experience. By mastering sensors and collision events, you can: Design complex trigger mechanisms: such as traps, switches, portals, etc. Optimize game physics effects: achieving more realistic interactions like elastic collisions and speed control. Enhance gameplay: creating unique level designs and challenges. We hope this tutorial helps you gain a deeper understanding of Dora SSR's physics system and encourages you to explore more advanced game features! ReminderIn practical development, effectively utilizing the advanced features of the physics engine can make your game more creative and engaging. Experiment with different parameters and functions to discover more possibilities!